home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / shells.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  6.4 KB  |  239 lines  |  [TEXT/R*ch]

  1. /*
  2.  * shells.c - Creates a shell using Pickover's generation method (see IEEE
  3.  *     CG&A November 1989).  One light source.  This thing tends to bring ray
  4.  *     tracers to their knees (lots of overlapping primitives, many quite
  5.  *     tiny) - it's meant as a study of a realistic yet pathological database.
  6.  *
  7.  *     There are various additional characteristics which can be diddled with
  8.  *     for different shell shapes (most pretty unrealistic, but there you go).
  9.  *     See Pickover's article for more information.  Do "shells -?" to see the
  10.  *     additional parameters which can be varied (listed at the end).
  11.  *
  12.  * Author:  Eric Haines, 3D/Eye, Inc.
  13.  *
  14.  * Modified:  Antonio Costa, INESC
  15.  *     Changed lib_get_opts to shells_get_opts
  16.  *     Corrected bug with light source definition
  17.  *     Changed several vars from COORD4 to COORD3
  18.  *
  19.  * Size factor determines the number of objects output.
  20.  *    Total objects = 180*(2**SF) spheres
  21.  *
  22.  *    Size factor    # spheres    # squares
  23.  *         1            360           1
  24.  *         2            720           1
  25.  *         3           1440          1
  26.  *         4           2880          1
  27.  *         5            5760          1
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <math.h>
  32. #include "def.h"
  33. #include "lib.h"
  34.  
  35. /* These may be read from the command line */
  36. static int size_factor      = 5;
  37. static int raytracer_format = OUTPUT_RT_DEFAULT;
  38. static int output_format    = OUTPUT_CURVES;
  39.  
  40.  
  41. #ifdef OUTPUT_TO_FILE
  42. static FILE * stdout_file = NULL;
  43. #else
  44. #define stdout_file stdout
  45. #endif /* OUTPUT_TO_FILE */
  46.  
  47.  
  48. static    double    fgamma = 1.0 ;    /* 0.01 to 3 */
  49. static    double    alpha = 0.0 ;    /* > 1 - 1.1 is good */
  50. static    double    beta = -2.0 ;    /* ~ -2 */
  51. static    double    a = 0.15 ;    /* exponent constant */
  52. static    double    k = 1.0 ;    /* relative size */
  53.  
  54. void    shells_show_usage()
  55. {
  56.     show_gen_usage() ;
  57.     fprintf(stderr, "-a alpha - alpha value (0 to 1.1 is good)\n");
  58.     fprintf(stderr, "-b beta - beta value (-2 is good)\n");
  59.     fprintf(stderr, "-g gamma - gamma value (0.01 to 3 is good)\n");
  60.     fprintf(stderr, "-e exponent - exponent value (0.15 is good)\n");
  61. }
  62.  
  63. int    shells_get_opts( argc, argv, p_size, p_rdr, p_curve )
  64. int    argc ;
  65. char    *argv[] ;
  66. int    *p_size, *p_rdr, *p_curve ;
  67. {
  68. int num_arg ;
  69. int val ;
  70. double fval ;
  71.  
  72.     num_arg = 0 ;
  73.  
  74.     while ( ++num_arg < argc ) {
  75.     if ( (*argv[num_arg] == '-') || (*argv[num_arg] == '/') ) {
  76.         switch( argv[num_arg][1] ) {
  77.         case 'g':    /* gamma */
  78.             if ( ++num_arg < argc ) {
  79.             sscanf( argv[num_arg], "%lf", &fval ) ;
  80.             if ( fval < 0.0 ) {
  81.                 fprintf( stderr,
  82.                     "bad gamma value %lf given\n",fval);
  83.                 shells_show_usage();
  84.                 return( TRUE ) ;
  85.             }
  86.             fgamma = fval ;
  87.             } else {
  88.             fprintf( stderr, "not enough args for -g option\n" ) ;
  89.             shells_show_usage();
  90.             return( TRUE ) ;
  91.             }
  92.             break ;
  93.         case 'a':    /* alpha */
  94.             if ( ++num_arg < argc ) {
  95.             sscanf( argv[num_arg], "%lf", &alpha ) ;
  96.             } else {
  97.             fprintf( stderr, "not enough args for -a option\n" ) ;
  98.             shells_show_usage();
  99.             return( TRUE ) ;
  100.             }
  101.             break ;
  102.         case 'b':    /* beta */
  103.             if ( ++num_arg < argc ) {
  104.             sscanf( argv[num_arg], "%lf", &beta ) ;
  105.             } else {
  106.             fprintf( stderr, "not enough args for -b option\n" ) ;
  107.             shells_show_usage();
  108.             return( TRUE ) ;
  109.             }
  110.             break ;
  111.         case 'e':    /* exponent selection */
  112.             if ( ++num_arg < argc ) {
  113.             sscanf( argv[num_arg], "%lf", &a ) ;
  114.             } else {
  115.             fprintf( stderr, "not enough args for -e option\n" ) ;
  116.             shells_show_usage();
  117.             return( TRUE ) ;
  118.             }
  119.             break ;
  120.  
  121.         case 's':    /* size selection */
  122.             if ( ++num_arg < argc ) {
  123.             sscanf( argv[num_arg], "%d", &val ) ;
  124.             if ( val < 1 ) {
  125.                 fprintf( stderr,
  126.                     "bad size value %d given\n",val);
  127.                 shells_show_usage();
  128.                 return( TRUE ) ;
  129.             }
  130.             *p_size = val ;
  131.             } else {
  132.             fprintf( stderr, "not enough args for -s option\n" ) ;
  133.             shells_show_usage();
  134.             return( TRUE ) ;
  135.             }
  136.             break ;
  137.         case 'c':    /* true curve output */
  138.             *p_curve = OUTPUT_CURVES ;
  139.             break ;
  140.         case 't':    /* tessellated curve output */
  141.             *p_curve = OUTPUT_PATCHES ;
  142.             break ;
  143.         case 'r':    /* renderer selection */
  144.             if ( ++num_arg < argc ) {
  145.             sscanf( argv[num_arg], "%d", &val ) ;
  146.             if ( val < OUTPUT_VIDEO || val >= OUTPUT_DELAYED ) {
  147.                 fprintf( stderr,
  148.                     "bad renderer value %d given\n",val);
  149.                 shells_show_usage();
  150.                 return( TRUE ) ;
  151.             }
  152.             *p_rdr = val ;
  153.             } else {
  154.             fprintf( stderr, "not enough args for -r option\n" ) ;
  155.             shells_show_usage();
  156.             return( TRUE ) ;
  157.             }
  158.             break ;
  159.         default:
  160.             fprintf( stderr, "unknown argument -%c\n",
  161.                 argv[num_arg][1] ) ;
  162.             shells_show_usage();
  163.             return( TRUE ) ;
  164.         }
  165.     } else {
  166.         fprintf( stderr, "unknown argument %s\n",
  167.             argv[num_arg] ) ;
  168.         shells_show_usage();
  169.         return( TRUE ) ;
  170.     }
  171.     }
  172.     return( FALSE ) ;
  173. }
  174.  
  175. main(argc,argv)
  176. int    argc ;
  177. char    *argv[] ;
  178. {
  179. double    r,angle ;
  180. long    i, steps ;
  181. COORD3    back_color, obj_color ;
  182. COORD3    from, at, up ;
  183. COORD4    light ;
  184. COORD4    sphere;
  185.  
  186.     PLATFORM_INIT(SPD_SHELLS);
  187.  
  188.     /* Start by defining which raytracer we will be using */
  189.     if ( shells_get_opts( argc, argv,
  190.             &size_factor, &raytracer_format, &output_format ) ) {
  191.     return EXIT_FAIL;
  192.     }
  193.     if ( lib_open( raytracer_format, "Shells.out" ) ) {
  194.     return EXIT_FAIL;
  195.     }
  196.  
  197.     /* output background color - UNC sky blue */
  198.     /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */
  199.     SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ;
  200.     lib_output_background_color( back_color ) ;
  201.  
  202.     /* output viewpoint */
  203.     SET_COORD3( from, -6.0, -60.0, 35.0 ) ;
  204.     SET_COORD3( at, 0.0, 8.0, -15.0 ) ;
  205.     SET_COORD3( up, 0.0, 0.0, 1.0 ) ;
  206.     lib_output_viewpoint( from, at, up, 45.0, 1.0, 0.5, 512, 512 ) ;
  207.  
  208.     /* output light sources */
  209.     SET_COORD4( light, -100.0, -100.0, 100.0, 1.0 ) ;
  210.     lib_output_light( light ) ;
  211.  
  212.     /* set up sphere color */
  213.     SET_COORD3( obj_color, 1.0, 0.8, 0.4 ) ;
  214.     lib_output_color( NULL, obj_color, 0.0, 0.8, 0.2, 0.5, 5.0, 0.0, 1.0 ) ;
  215.  
  216.     steps = 180.0 * pow( 2.0, (double)size_factor ) ;
  217.     for ( i = -steps*2/3; i <= steps/3 ; ++i ) {
  218.     PLATFORM_MULTITASK();
  219.  
  220.     angle = 3.0 * 6.0 * PI * (double)i / (double)steps ;
  221.     r = k * exp( a * angle ) ;
  222.     sphere[X] = r * sin( angle ) ;
  223.     sphere[Y] = r * cos( angle ) ;
  224.     if ( alpha > 0.0 ) {
  225.         /* alternate formula: z = alpha * angle */
  226.         sphere[Z] = alpha * angle ;
  227.     } else {
  228.         sphere[Z] = beta * r ;
  229.     }
  230.     sphere[W] = r / fgamma ;
  231.     lib_output_sphere( sphere, output_format ) ;
  232.     }
  233.  
  234.     lib_close();
  235.  
  236.     PLATFORM_SHUTDOWN();
  237.     return EXIT_SUCCESS;
  238. }
  239.